package com.jsu.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jsu.user.mapper.IntegralRuleMapper;
import com.jsu.user.mapper.PointDetailMapper;
import com.jsu.user.service.PointDetailService;
import com.jsu.user.service.WebRuleService;
import lombok.extern.slf4j.Slf4j;
import org.example.model.common.dtos.ResponseResult;
import org.example.model.common.enums.RedisCodeEnum;
import org.example.model.common.enums.WebHttpCodeEnum;
import org.example.model.user.pojo.PointDetail;
import org.example.model.user.pojo.Rule;
import org.example.model.user.pojo.User;
import org.example.utils.common.IdsUtils;
import org.example.utils.common.RedisCache;
import org.example.utils.common.WebJwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Date;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
@Transactional
public class PointDetailServiceImpl extends ServiceImpl<PointDetailMapper, PointDetail> implements PointDetailService {
   @Autowired
   private PointDetailMapper pointDetailMapper;
   @Autowired
   private WebUserServiceImpl userService;
   @Autowired(required = false)
   private StringRedisTemplate redisCache;
   @Autowired
   private WebRuleServiceImpl ruleService;
   private static final ObjectMapper mapper = new ObjectMapper();



    /**
     * 根据userId和ruleId查找距离当前时间最近的签到记录
     * @param userId
     * @param ruleId
     * @return PointDetail
     */
    @Override
    public PointDetail getUserPointDetail(int userId, int ruleId) {
        User user = userService.getById(userId);
        if (Objects.isNull(user)) {
            return null;
        }
        //从redis查询
        String key = RedisCodeEnum.POINT_DETAIL.getMsg()+user.getPkId();
        PointDetail pointDetail = ruleService.getLatestPointDetail(key);
        if(!Objects.isNull(pointDetail))
            return pointDetail;
        //从数据库查询
        QueryWrapper<PointDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId)
                .eq("point_rule_id", ruleId)
                .orderByDesc("time")
                .last("LIMIT 1");

        return pointDetailMapper.selectOne(queryWrapper);
    }

    /**
     * 返回当前用户的积分明细
     * @return pointDetail集合
     */
    @Override
    public ResponseResult getPointDetail(String token) {
        long phone = Objects.requireNonNull(WebJwtUtil.getClaimsBody(token)).get("id", Long.class);
        User user =(User) userService.findUser(token).getData();
        if (Objects.isNull(user)) {
            return ResponseResult.errorResult(WebHttpCodeEnum.DATA_NOT_EXIST);
        }
        //从redis查询
        String key = RedisCodeEnum.POINT_DETAIL.getMsg()+user.getPkId();
        List<String> points = redisCache.opsForList().range(key,0,-1);
        // 反序列化为List<PointDetail>
        List<PointDetail> pointDetailList = new ArrayList<>();
        for (String pointDetailJson : points) {
            try {
                PointDetail pointDetail = mapper.readValue(pointDetailJson, PointDetail.class);
                pointDetailList.add(pointDetail);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }
        if(pointDetailList.size()>0)
            return ResponseResult.okResult(pointDetailList);

        //从数据库中查询
        QueryWrapper<PointDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",user.getPkId())
                .orderByDesc("time");
        List<PointDetail> pointDetails = pointDetailMapper.selectList(queryWrapper);
        if (pointDetails.size()==0||pointDetails.isEmpty()) {
            return ResponseResult.errorResult(WebHttpCodeEnum.DATA_NOT_EXIST,"还没有明细");
        }
        return ResponseResult.okResult(pointDetails);
    }

    /**
     * 添加积分明细记录
     * @param pointDetail
     * @return
     */
    @Transactional
    @Override
    public ResponseResult addPointDetail(PointDetail pointDetail) {
        //添加到Redis中
        String key = RedisCodeEnum.POINT_DETAIL.getMsg()+pointDetail.getUserId()+RedisCodeEnum.A.getMsg()+pointDetail.getRuleId();
        try {
            String json = mapper.writeValueAsString(pointDetail);
            redisCache.opsForValue().set(key,json);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        //添加到数据库中
        int count = pointDetailMapper.insert(pointDetail);
        if (count<=0) {
            return ResponseResult.errorResult(WebHttpCodeEnum.FAIL,"添加失败");
        }
        return ResponseResult.okResult(200,"成功");
    }

    /**
     * 判断用户是否签到
     * @param userId
     * @param pkId
     * @return
     */
    public boolean isSign(Integer pkId) {
        PointDetail pointDetail = getUserPointDetail(pkId, 1);
        if (Objects.isNull(pointDetail)) {
            return false;
        }
        Date date = pointDetail.getTime();
        LocalDate pointDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate today = LocalDate.now();
        return pointDate.isEqual(today);
    }
}
